package com.vivo.ic.dm;

import java.util.Collection;

import com.vivo.ic.VLog;
import com.vivo.ic.dm.impl.DownloadNotification;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.text.TextUtils;

/**
 * Created by bruce on 2016年10月28日
 */

public abstract class DownloadNotifier implements DownloadNotification {
    public static final String TAG = Constants.PRE_TAG + "DownloadNotifier";

    public final Context mContext;
    public final Resources mRes;
    public final NotificationManager mNotificationManager;
    public NotificationItem mLastNotiItem;
    
    /**
     * @param context
     */
    public DownloadNotifier(Context context) {
        mContext = context;
        mRes = context.getResources();
        mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    }
    
    @Override
    public void updateWith(Collection<DownloadInfo> downloads) {
        updateActiveNotification(downloads);
        updateCompletedNotification(downloads);        
    }
    
    void updateActiveNotification(Collection<DownloadInfo> downloads) {
        // 重新计算所有的notification信息
        NotificationItem item = getActiveNotificationItem(downloads);
        
        // 取消上次的notification
        if (mLastNotiItem != null && (item == null || item.mId != mLastNotiItem.mId)) {
            mNotificationManager.cancel(getNotiIdDownloading(mLastNotiItem.mId));
            mNotificationManager.cancel(getNotiIdDownloadFinished(mLastNotiItem.mId));
        }
        
        // post本次需要的notification
        if (item != null) {
            mLastNotiItem = item;
            postActiveNotification(item);
        }
    }
    
    public void updateCompletedNotification(Collection<DownloadInfo> downloads) {
        for (DownloadInfo download : downloads) {
            postCompleteNotification(download);
        }
    }

    NotificationItem getActiveNotificationItem(Collection<DownloadInfo> downloads) {
        NotificationItem item = null;

        for (DownloadInfo download : downloads) {

            // 除了可见的正在下载，其他所有下载通知不显示
            if (!isActiveAndVisible(download)) {
                continue;
            }

            long max = download.mTotalBytes;
            long current = download.mCurrentBytes;
            long id = download.mId;
            String title = download.mTitle;

            if (TextUtils.isEmpty(title)) {
                title = getStringUnknowTitle();
            }

            if (item == null) {
                item = new NotificationItem();
                item.mId = (int) id;
                item.mDescription = download.mDescription;
                item.mTotalCurrent = current;
                item.mTotalTotal = max;
                item.mTitle = title;
            }
            item.mTitleCount = item.mTitleCount + 1;
        }
        
        return item;
    }

    public boolean isActiveAndVisible(DownloadInfo download) {
        return download.mStatus >= 100 && download.mStatus < Downloads.Impl.STATUS_SUCCESS
                && download.mStatus != Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR
                && download.mVisibility != Downloads.Impl.VISIBILITY_HIDDEN
                && download.mVisibility != Downloads.Impl.VISIBILITY_VISIBLE_COMPLETED
                && download.mControl != Downloads.Impl.CONTROL_PAUSED;
    }
    
    public boolean isCompleteAndVisible(DownloadInfo download) {
        return (download.mStatus >= Downloads.Impl.STATUS_SUCCESS
                || download.mStatus == Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR)
                && download.mVisibility != Downloads.Impl.VISIBILITY_HIDDEN
                && download.mVisibility != Downloads.Impl.VISIBILITY_VISIBLE_PROGRESS;
    }
    
    void postActiveNotification(NotificationItem item) {
        final Notification.Builder builder = new Notification.Builder(mContext);

        int iconResource = getIconIdDownloading();
        
        builder.setSmallIcon(iconResource);
        builder.setOngoing(true);

        if (!TextUtils.isEmpty(item.mDescription)) {
            builder.setContentText(item.mDescription);
        }
        
        String title;
        if (item.mTitleCount > 1) {
            title = getStringMultiDownloading(item.mTitleCount);
        } else {
            title = item.mTitle;
            if (item.mTotalTotal != -1 && (item.mTotalTotal < item.mTotalCurrent)) {
                VLog.w(TAG, "updateActiveNotification: mTotalCurrent is: " + item.mTotalCurrent
                        + " more than mTotalTotal: " + item.mTotalTotal + " and set to same");
                item.mTotalTotal = item.mTotalCurrent;
            }
            
            builder.setProgress((int) item.mTotalTotal, (int) item.mTotalCurrent, item.mTotalTotal == -1);
            builder.setContentInfo(buildPercentageLabel(mContext, item.mTotalTotal, item.mTotalCurrent));
        }
        
        builder.setContentTitle(title);

        final Intent intent = new Intent(Downloads.Action.NOTI_DOWNLOAD_CLICKED, null, mContext, DownloadReceiver.class);
        builder.setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent, 0));
        mNotificationManager.cancel(getNotiIdDownloadFinished(item.mId));
        mNotificationManager.cancel(getNotiIdDownloadWarn());
        mNotificationManager.notify(getNotiIdDownloading(item.mId), builder.getNotification());
    }

    void postCompleteNotification(DownloadInfo download) {

        // 除了可见的正在下载，其他所有下载通知不显示
        if (!isCompleteAndVisible(download)) {
            // DownloadReceiver在接收到ACTION_HIDE后，service线程无法保证mVisibility字段完全同步
            // 所以在这里再次进行notification的hide操作，防止状态栏有很多通知时，一键清除还会出现下载完成的通知
            mNotificationManager.cancel(getNotiIdDownloadFinished((int)download.mId));
            return;
        }
        
        String title = download.mTitle;
        long id = download.mId;
        int status = download.mStatus;
        long lastMod = download.mLastMod;

        Notification.Builder builder = new Notification.Builder(mContext);
        if (title == null || title.length() == 0) {
            title = getStringUnknowTitle();
        }

        Uri contentUri = ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, id);

        String caption = null;
        if (Downloads.Impl.isStatusError(status)) {
            builder.setSmallIcon(getIconIdDownloadFailed());
            caption = getStringDownloadFailed();
        } else {
            builder.setSmallIcon(getIconIdDownloadSuccess());
            caption = getStringDownloadSuccess();
        }
        
        builder.setWhen(lastMod);
        builder.setContentTitle(title);
        builder.setContentText(caption);
        
        final Intent intent = new Intent(Downloads.Action.NOTI_COMPLETE_CLICKED, contentUri, mContext, DownloadReceiver.class);
        builder.setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent, 0));

        final Intent hideIntent = new Intent(Downloads.Action.NOTI_HIDE, contentUri, mContext, DownloadReceiver.class);
        builder.setDeleteIntent(PendingIntent.getBroadcast(mContext, 0, hideIntent, 0));

        Notification notification = builder.getNotification();
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        mNotificationManager.cancel(getNotiIdDownloading((int)id));
        mNotificationManager.notify(getNotiIdDownloadFinished((int)id), notification);
    }
    
    String buildPercentageLabel(Context context, long totalBytes, long currentBytes) {
        if (totalBytes <= 0) {
            return null;
        } else {
            final int percent = (int) (100 * currentBytes / totalBytes);
            return percent + "%";
        }
    }
    
    @Override
    public void cancelAllNotification(int id) {
        VLog.d(TAG, "cancelAllNotification() " + mNotificationManager);
        if (mNotificationManager != null) {
            mNotificationManager.cancel(getNotiIdDownloading(id));
            mNotificationManager.cancel(getNotiIdDownloadFinished(id));
            mNotificationManager.cancel(getNotiIdDownloadWarn());
        }
    }
    
    @Override
    public void showNetPauseNotification() {
        VLog.d(TAG, "showNetPauseNotification() " + mNotificationManager);
        final Intent intent = new Intent(Downloads.Action.NOTI_CONFIRM, null, mContext, DownloadReceiver.class);
        PendingIntent contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
        
        Notification.Builder builder = new Notification.Builder(mContext);
        builder.setSmallIcon(getIconIdDownloadWarn());
        builder.setContentText(getStringDownloadWarnContent());
        builder.setContentTitle(getStringDownloadWarnTiltle());
        builder.setContentIntent(contentIntent);
        
        Notification notification = builder.getNotification();
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        // Fire away.
        if (mNotificationManager != null) {
            VLog.d(TAG, "mNotificationManager.notify");
            mNotificationManager.notify(getNotiIdDownloadWarn(), notification);
        }
    }
    
    @Override
    public void hideNetPauseNotification() {
        VLog.d(TAG, "hideNetPauseNotification() " + mNotificationManager);
        if (mNotificationManager != null) {
            mNotificationManager.cancel(getNotiIdDownloadWarn());
        }
    }

    public static class NotificationItem {
        int mId;
        int mTitleCount = 0;
        long mTotalCurrent = 0;
        long mTotalTotal = 0;
        String mDescription;
        String mTitle;
    }
    
    public abstract String getStringUnknowTitle();
    public abstract String getStringMultiDownloading(int downloadNum);
    public abstract String getStringDownloadFailed();
    public abstract String getStringDownloadSuccess();
    public abstract String getStringDownloadWarnTiltle();
    public abstract String getStringDownloadWarnContent();
    
    public abstract int getIconIdDownloading();
    public abstract int getIconIdDownloadSuccess();
    public abstract int getIconIdDownloadFailed();
    public abstract int getIconIdDownloadWarn();
    
    public abstract int getNotiIdDownloading(int id);
    public abstract int getNotiIdDownloadFinished(int id);
    public abstract int getNotiIdDownloadWarn();
}
